from django.contrib.gis.db.models.functions import Distance
from django.contrib.gis.geos import Point
from django.db import models
from rest_framework import pagination
from rest_framework.permissions import IsAuthenticated
from rest_framework.viewsets import GenericViewSet, ViewSet
from django.conf import settings
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from .paginations import PageNumberPagination
import json
from datetime import datetime
from FSJY.utils.buyHighResponse import APIResponse
from .models import UserProfile, userPhotos,relationship
from rest_framework.decorators import action
from FSJY.utils.check_telephone import check_telephone
from .jythrotting import SMSThrottle
from django.core.cache import cache
# 生产者
from FSJY.libs.sendSms import get_random_code, sms_settings
from celery_task.celery_sms import celery_send_message
from .serializers import CodeLoginSerializer, UserProfileSerializer
import json


# Create your views here.
class LoginView(GenericViewSet):
    queryset = UserProfile.objects.all()
    serializer_class = None

    def wxlogin(self, request, *args, **kwargs):
        # 验证码登录
        return

    @action(methods=['post'], detail=False)
    def code_login_register(self, request, *args, **kwargs):
        # 验证码登录
        print(request.data)
        ser = CodeLoginSerializer(data=request.data)
        if ser.is_valid(raise_exception=True):
            print("成功登陆，返回token")
            return APIResponse(status=200, statusCode=200, code=200, message='success', token=ser.context['token'],
                               data=ser.data)
        else:
            return APIResponse(status=400, statusCode=400, code=400, message='file', data=ser.errors)


class sendSmsView(ViewSet):
    throttle_classes = [SMSThrottle]

    @action(methods=['post'], detail=False)
    def send_sms(self, request, *args, **kwargs):
        print(request.data["telephone"])
        telephone = request.data['telephone']
        result = check_telephone(telephone)
        if result:
            # 生成验证码
            code = get_random_code.get_rendom_code()
            # 发送短信，添加到任务队列
            celery_send_message.delay(sms_settings.tid, telephone, (code, sms_settings.timeout))
            # 保存验证码
            cache.set(settings.PHONE_CACHE_KEY % request.data['telephone'], code, settings.SMS_CODE_EXPIRE_TIME)
            return APIResponse(status=200, statusCode=200, code=200, message='success')
        else:
            return APIResponse(status=200, statusCode=200, code=200, message='手机号格式错误')


# ... 已有代码 ...
class UserView(GenericViewSet):
    permission_classes = [IsAuthenticated]
    authentication_classes = [JSONWebTokenAuthentication]
    pagination_class = PageNumberPagination
    queryset = UserProfile.objects.all()
    # 新增位置更新接口
    @action(methods=['post'], detail=False)
    def update_location(self, request, *args, **kwargs):
        user = request.user
        # 前端传递经纬度
        la = request.data.get('latitude')
        lng = request.data.get('longitude')
        print(la, lng)
        # 校验坐标有效性
        if not all([la, lng]):
            return APIResponse(status=400, message='缺少经纬度参数')
        try:
            new_location = Point(float(lng), float(la), srid=4326)
            # 仅当位置变化超过1公里时更新（优化写入频率）
            if user.location and user.location.distance(new_location) < 1000:
                return APIResponse(status=200, message='位置未发生显著变化')
            user.location = new_location
            user.save(update_fields=['location'])
            return APIResponse(status=200, message='位置更新成功')
        except (TypeError, ValueError) as e:
            return APIResponse(status=400, message='坐标格式错误')

    @action(methods=['get'], detail=False)
    def recommend(self, request, *args, **kwargs):
        user = request.user
        # 优先使用用户的最新位置（如果已保存）
        if not user.location:
            return APIResponse(status=400, message='请先更新位置信息')
        cache_key=f"recommend_{user.id}"
        query_page=request.GET.get('page')
        print("当前页是",query_page)
        # 当page==1说明是第一次请求，删除之前的缓存重新添加，防止提交过的数据再次提交
        if query_page==str(1):
            cache.delete(cache_key)
            print("删除缓存")
        cache_ids=cache.get(cache_key)
        print("缓存",cache_ids)
        # 尝试获取缓存后的分页id列表
        if not cache_ids:
            # 筛选出不需要推荐的人
            excluded_ids = user.like_people.through.objects.filter(
                myid=user
            ).values_list('liked_user_id', flat=True)
            print("不需要推荐的人",excluded_ids)
            # 筛选出需要推荐的人
            base_query = UserProfile.objects.filter(
                location__distance_lte=(user.location, 500000)
            ).exclude(
                # django默认是and查询，使用or查寻的话必须要使用models.Q
                models.Q(gender=user.gender) |
                models.Q(id__in=excluded_ids) |
                models.Q(id=user.id)
            ).annotate(
                # 计算距离
                distance=Distance('location', user.location)
            ).order_by('id')
            # 把所有需要推荐的人的id缓存起来
            cache_ids=list(base_query.values_list("id",flat=True))
            # 直接使用用户存储的位置进行查询，缓存一天
            cache.set(cache_key,cache_ids,60*60*24)
        #  根据当前页码获取对应的id范围
        #    如果每页显示10条，当前请求的是第2页，那么返回的page就是ID列表中第11到20个元素。
        page=self.paginate_queryset(cache_ids)
        print("当前页",page)
        if page is not None:
            # 通过id列表获取完整对象，保持排序
            final_queryset=UserProfile.objects.filter(id__in=page).annotate(
                distance=Distance('location', user.location)
            ).exclude(id=user.id).order_by('-id')
            serializer = UserProfileSerializer(final_queryset, many=True)
            return self.get_paginated_response(serializer.data)
        return APIResponse(status=200, message='没有更多数据啦!')
    @action(methods=["post"], detail=False)
    def like_or_dislike(self, request, *args, **kwargs):
        # 从请求中获取用户ID和被喜欢的用户ID
        myid = request.user
        liked_user_id = request.data.get("liked_user_id")
        liked_user_obj = UserProfile.objects.get(id=liked_user_id)
        action = request.data.get("action")
        # 检查该用户是否存在
        if not liked_user_id:
            return APIResponse(status=400, message="缺少被喜欢的用户ID",code=400)
        # 查找喜欢的人是否存在
        res=relationship.objects.filter(myid=myid,liked_user_id=liked_user_obj)
        if res:
            return APIResponse(status=400,message="喜欢的人已经喜欢过了哟！",code=400)
        if action == "like":
            # 如果喜欢，则创建关系
            relationship.objects.create(myid=request.user,liked_user_id=liked_user_obj,is_like=True)
        else:
            # 如果不喜欢，则创建关系
            relationship.objects.create(myid=request.user,liked_user_id=liked_user_obj,is_like=False)
        return APIResponse(status=200, message="操作成功",code=200)
